home *** CD-ROM | disk | FTP | other *** search
/ The 640 MEG Shareware Studio 5 / The 640 Meg Shareware Studio CD-ROM Volume V (Data Express)(1994).ISO / amiga / awwari11.lha / Awwari / Source / Awwari.c next >
C/C++ Source or Header  |  1994-05-09  |  21KB  |  719 lines

  1. /*
  2.  *  Awwari - An Awari game by ! Wizard Works !
  3.  *  Written by Stefan Zeiger in 1993-1994
  4.  *  (c) 1993-1994 by Stefan Zeiger
  5.  *  Freely distributable, All other rights reserved
  6.  *
  7.  *  I am not very proud of this piece of source. I hacked the first
  8.  *  first version together on one afternoon. Don't blame me if you
  9.  *  can't make your way through this code jungle ;)
  10.  *
  11.  *  22.11.1993  0.1   Project started
  12.  *  23.11.1993  0.2   Playable; dumb computer
  13.  *  27.11.1993  0.3   AwariMove() added, PerformMove() rewritten to use AwariMove()
  14.  *              0.4   Simple computer strategy added
  15.  *  28.11.1993  0.5   Auto finish added
  16.  *              0.6   Recursive computer strategy added
  17.  *  12.11.1993  0.7   Updated with new Triton system
  18.  *  23.12.1993  1.0   First release, using Triton 0.106
  19.  *  20.04.1994  1.1b1 Rewritten for triton.library
  20.  *  09.05.1994  1.1   Released Awwari 1.1
  21.  *
  22.  */
  23.  
  24. #define AWWARI_VERSION "1.1"
  25. #define AWWARI_DATE    "9.5.94"
  26.  
  27.  
  28. /////////////////////////////////////////////////////////////////////////////////////////////////////////////
  29. //////////////////////////////////////////////////////////////////////////////////////// Include our stuff //
  30. /////////////////////////////////////////////////////////////////////////////////////////////////////////////
  31.  
  32. #include <libraries/triton.h>
  33. #include <proto/intuition.h>
  34. #include <proto/triton.h>
  35. #include <proto/dos.h>
  36. #include <stdio.h>
  37. #include <stdlib.h>
  38. #include <time.h>
  39. #include <math.h>
  40.  
  41.  
  42. /////////////////////////////////////////////////////////////////////////////////////////////////////////////
  43. ////////////////////////////////////////////////////////////////////////////////////////////////// Windows //
  44. /////////////////////////////////////////////////////////////////////////////////////////////////////////////
  45.  
  46. ProjectDefinition(about_trwintags)
  47. {
  48.   BeginRequester("About Awwari...",TRWP_MOUSEPOINTER),
  49.  
  50.   VertGroupA, Space,  CenteredText3("Awwari " AWWARI_VERSION),
  51.               Space,  CenteredText_BS("An Awari game by ! Wizard Works !"),
  52.               Space,  CenteredText("⌐ 1993-1994 by Stefan Zeiger"),
  53.               Space,  HorizSeparator,
  54.               Space,  CenteredText("This program is using the"),
  55.               SpaceS, CenteredText("Triton GUI creation system"),
  56.               SpaceS, CenteredText("which is ⌐ by Stefan Zeiger"),
  57.               Space,  EndGroup,
  58.  
  59.   BeginRequesterGads,
  60.   CenteredButtonRE("_OK",1),
  61.   EndRequester
  62. };
  63.  
  64. STRPTR cycle_entries_player[]=
  65. {
  66.   "Human",
  67.   "Computer",
  68.   NULL
  69. };
  70.  
  71. STRPTR cycle_entries_first[]=
  72. {
  73.   "Player 1",
  74.   "Player 2",
  75.   "Random",
  76.   NULL
  77. };
  78.  
  79. STRPTR cycle_entries_level[]=
  80. {
  81.   "1",
  82.   "2",
  83.   "3",
  84.   "4",
  85.   "5",
  86.   NULL
  87. };
  88.  
  89. ProjectDefinition(main_trwintags)
  90. {
  91.   WindowTitle("Awwari " AWWARI_VERSION " - ⌐ 1993-1994 by Stefan Zeiger"),
  92.   WindowPosition(TRWP_CENTERDISPLAY), WindowID(1),
  93.  
  94.   BeginMenu("Project"),
  95.     MenuItem("?_About...",1001),
  96.     ItemBarlabel,
  97.     MenuItem("Q_Quit",1002),
  98.  
  99.   VertGroupA,
  100.     Space,  NamedSeparator("Options"),
  101.     Space,  HorizGroupEAC,
  102.               HorizGroupS, Space, TextN("Pl_ayer 1"), TRAT_ID, 102, EndGroup,
  103.               SpaceB,
  104.                 TROB_Cycle,           (ULONG) cycle_entries_player,
  105.                   TRAT_ID,            (ULONG) 102,
  106.                   TRAT_Value,         (ULONG) 0,
  107.               Space,
  108.               HorizGroupS, Space, TextN("_First move"), TRAT_ID, 104, EndGroup,
  109.               SpaceB,
  110.                 TROB_Cycle,           (ULONG) cycle_entries_first,
  111.                   TRAT_ID,            (ULONG) 104,
  112.                   TRAT_Value,         (ULONG) 2,
  113.               Space,
  114.             EndGroup,
  115.     Space,  HorizGroupEAC,
  116.               HorizGroupS, Space, TextN("Pla_yer 2"), TRAT_ID, 103, EndGroup,
  117.               SpaceB,
  118.                 TROB_Cycle,           (ULONG) cycle_entries_player,
  119.                   TRAT_ID,            (ULONG) 103,
  120.                   TRAT_Value,         (ULONG) 1,
  121.               Space,
  122.               HorizGroupS, Space, TextN("_Level"), TRAT_ID, 105, EndGroup,
  123.               SpaceB,
  124.                 TROB_Cycle,           (ULONG) cycle_entries_level,
  125.                   TRAT_ID,            (ULONG) 105,
  126.                   TRAT_Value,         (ULONG) 0,
  127.               Space,
  128.             EndGroup,
  129.     Space,  HorizGroupE, Space, ButtonR("_Start game",110), Space, Button("_Quit game",112), Disabled, Space, Button("A_uto finish",111), Disabled, Space, EndGroup,
  130.     Space,  NamedSeparator("Status"),
  131.     Space,  HorizGroup, Space, FrameBox, ObjectBackfillB, VertGroup|TRGR_FIXVERT, SpaceS, HorizGroupSC, Space, TextN("Ready."),ID(101), TRAT_MinWidth, 40, Space, EndGroup, SpaceS, EndGroup, Space, EndGroup,
  132.     Space,  NamedSeparator("Playfield"),
  133.     Space,  HorizGroupEA,
  134.               Space, VertGroupA, SpaceS, CenteredText3("1"), SpaceS, EndGroup,
  135.               Space, IntegerBox(3,6,3),
  136.               Space, IntegerBox(3,5,3),
  137.               Space, IntegerBox(3,4,3),
  138.               Space, IntegerBox(3,3,3),
  139.               Space, IntegerBox(3,2,3),
  140.               Space, IntegerBox(3,1,3),
  141.               Space, HorizGroupS, Space, EndGroup,
  142.               Space, EndGroup,
  143.     Space,  HorizGroupEAC,
  144.               Space, IntegerBox(0,7,3),
  145.               Space, Button("_1",201), Disabled,
  146.               Space, Button("_2",202), Disabled,
  147.               Space, Button("_3",203), Disabled,
  148.               Space, Button("_4",204), Disabled,
  149.               Space, Button("_5",205), Disabled,
  150.               Space, Button("_6",206), Disabled,
  151.               Space, IntegerBox(0,17,3),
  152.               Space, EndGroup,
  153.     Space,  HorizGroupEA,
  154.               Space, HorizGroupS, Space, EndGroup,
  155.               Space, IntegerBox(3,11,3),
  156.               Space, IntegerBox(3,12,3),
  157.               Space, IntegerBox(3,13,3),
  158.               Space, IntegerBox(3,14,3),
  159.               Space, IntegerBox(3,15,3),
  160.               Space, IntegerBox(3,16,3),
  161.               Space, VertGroupA, SpaceS, CenteredText3("2"), SpaceS, EndGroup,
  162.               Space, EndGroup,
  163.     Space, EndGroup, EndProject
  164. };
  165.  
  166.  
  167. /////////////////////////////////////////////////////////////////////////////////////////////////////////////
  168. //////////////////////////////////////////////////////////////////////////////////////////// Our own names //
  169. /////////////////////////////////////////////////////////////////////////////////////////////////////////////
  170.  
  171. VOID                  SetInfoString           (STRPTR);
  172. VOID                  StartGame               (VOID);
  173. VOID                  QuitGame                (VOID);
  174. VOID                  Winner                  (UWORD);
  175. VOID                  MakeTurn                (UWORD player, BOOL setsecondturn);
  176. VOID                  SetPositionGadgets      (UWORD);
  177. VOID                  DisablePositionGadgets  (VOID);
  178. VOID                  ActualizeDisplay        (VOID);
  179. VOID                  PerformMove             (UWORD,UWORD);
  180. VOID                  ComputeMove             (UWORD);
  181. UWORD                 BestMove                (UBYTE awarifield[7][2], UWORD aplayer, UWORD *bestval);
  182. UWORD                 BestMoveNR              (UBYTE awarifield[7][2], UWORD aplayer);
  183. UWORD                 AwariMove               (UBYTE awarifield[7][2], UWORD player, UWORD field);
  184. struct TR_Project   * main_project;
  185. UWORD                 player1,
  186.                       player2,
  187.                       first,
  188.                       level,
  189.                       currentplayer,
  190.                       currentdepth;
  191. BOOL                  gamerunning;
  192. UBYTE                 playfield               [7][2];
  193. UBYTE                 display                 [7][2];
  194. UWORD                 i,
  195.                       j;
  196. BOOL                  posgaddisabled          [6];
  197. BOOL                  secondturn;
  198.  
  199.  
  200. /////////////////////////////////////////////////////////////////////////////////////////////////////////////
  201. //////////////////////////////////////////////////////////////////////////////////////////// Main function //
  202. /////////////////////////////////////////////////////////////////////////////////////////////////////////////
  203.  
  204. VOID do_main(VOID)
  205. {
  206.   BOOL close_me=FALSE;
  207.   struct TR_Message *trmsg;
  208.  
  209.   for(i=0;i<=1;i++)
  210.   {
  211.     for(j=0;j<=5;j++) display[j][i]=3;
  212.     display[6][i]=0;
  213.   }
  214.  
  215.   for(j=0;j<=5;j++) posgaddisabled[j]=TRUE;
  216.  
  217.   if(main_project=TR_OpenProject(Application,main_trwintags))
  218.   {
  219.     while(!close_me)
  220.     {
  221.       TR_Wait(Application,NULL);
  222.       while(trmsg=TR_GetMsg(Application))
  223.       {
  224.         switch(trmsg->trm_Class)
  225.         {
  226.           case TRMS_CLOSEWINDOW:
  227.             close_me=TRUE;
  228.             break;
  229.  
  230.           case TRMS_ERROR:
  231.             DisplayBeep(NULL);
  232.             break;
  233.  
  234.           case TRMS_NEWVALUE:
  235.             break;
  236.  
  237.           case TRMS_ACTION:
  238.             switch(trmsg->trm_ID)
  239.             {
  240.               case 110:
  241.                 StartGame();
  242.                 break;
  243.               case 111:
  244.                 player1=1;
  245.                 player2=1;
  246.                 TR_SetAttribute(main_project,112,TRAT_Disabled,1L);
  247.                 TR_SetAttribute(main_project,111,TRAT_Disabled,1L);
  248.                 MakeTurn(currentplayer,FALSE);
  249.                 break;
  250.               case 112:
  251.                 QuitGame();
  252.                 SetInfoString("Ready.");
  253.                 break;
  254.               case 201:
  255.                 PerformMove(currentplayer,currentplayer?0:5);
  256.                 break;
  257.               case 202:
  258.                 PerformMove(currentplayer,currentplayer?1:4);
  259.                 break;
  260.               case 203:
  261.                 PerformMove(currentplayer,currentplayer?2:3);
  262.                 break;
  263.               case 204:
  264.                 PerformMove(currentplayer,currentplayer?3:2);
  265.                 break;
  266.               case 205:
  267.                 PerformMove(currentplayer,currentplayer?4:1);
  268.                 break;
  269.               case 206:
  270.                 PerformMove(currentplayer,currentplayer?5:0);
  271.                 break;
  272.               case 1001:
  273.                 TR_AutoRequest(Application,main_project,about_trwintags);
  274.                 break;
  275.               case 1002:
  276.                 close_me=TRUE;
  277.             }
  278.             break;
  279.         }
  280.         TR_ReplyMsg(trmsg);
  281.       }
  282.     }
  283.     TR_CloseProject(main_project);
  284.   }
  285.   else DisplayBeep(NULL);
  286. }
  287.  
  288.  
  289. /////////////////////////////////////////////////////////////////////////////////////////////////////////////
  290. /////////////////////////////////////////////////////////////////////////////////////////// Entry function //
  291. /////////////////////////////////////////////////////////////////////////////////////////////////////////////
  292.  
  293. int main(void)
  294. {
  295.   if(TR_OpenTriton(TRITON10VERSION,
  296.     TRCA_Name,    "Awwari",
  297.     TRCA_LongName,"Awwari",
  298.     TRCA_Info,    "An Awari game for the Workbench\nWritten and ⌐ 1993-1994 by Stefan Zeiger",
  299.     TRCA_Release, "1.1",
  300.     TRCA_Date,    AWWARI_DATE,
  301.     TAG_END))
  302.   {
  303.     do_main();
  304.     TR_CloseTriton();
  305.     return 0;
  306.   }
  307.  
  308.   puts("Can't open triton.library.");
  309.   return 20;
  310. }
  311.  
  312.  
  313. /////////////////////////////////////////////////////////////////////////////////////////////////////////////
  314. ////////////////////////////////////////////////////////////////////////////////////////// Evaluate a move //
  315. /////////////////////////////////////////////////////////////////////////////////////////////////////////////
  316.  
  317. UWORD MyRand(VOID)
  318. {
  319.   unsigned int clock[2];
  320.   WORD seed[3];
  321.  
  322.   (VOID)timer(clock);
  323.  
  324.   seed[0]=(WORD)clock[0];
  325.   seed[1]=(WORD)clock[1]>>16;
  326.   seed[2]=(WORD)clock[1];
  327.  
  328.   return (UWORD)(jrand48((UWORD *)seed));
  329. }
  330.  
  331.  
  332. /////////////////////////////////////////////////////////////////////////////////////////////////////////////
  333. ////////////////////////////////////////////////////////////////////////////////////////// Evaluate a move //
  334. /////////////////////////////////////////////////////////////////////////////////////////////////////////////
  335.  
  336. #define AM_OK         0L
  337. #define AM_EMPTYFIELD 1L
  338. #define AM_EXTRATURN  2L
  339. #define AM_1WINS      3L
  340. #define AM_2WINS      4L
  341. #define AM_TIE        5L
  342.  
  343. UWORD AwariMove(UBYTE awarifield[7][2], UWORD aplayer, UWORD afield)
  344. {
  345.   UBYTE stonesleft=awarifield[afield][aplayer];
  346.   UBYTE cfield=afield;
  347.   UBYTE cplayer=aplayer;
  348.   UBYTE nextplayer;
  349.  
  350.   if(stonesleft==0) return AM_EMPTYFIELD;
  351.  
  352.   awarifield[afield][aplayer]=0;
  353.  
  354.   while(stonesleft>0)
  355.   {
  356.     cfield++;
  357.     if(cfield==7) { cfield=0; cplayer++; cplayer%=2; }
  358.     awarifield[cfield][cplayer]++;
  359.     stonesleft--;
  360.   }
  361.   if(cfield!=6)
  362.   {
  363.     if((awarifield[cfield][cplayer]==1)&&(awarifield[5-cfield][(cplayer+1)%2]!=0))
  364.     {
  365.       awarifield[6][aplayer]+=(awarifield[cfield][cplayer]+awarifield[5-cfield][(cplayer+1)%2]);
  366.       awarifield[cfield][cplayer]=0;
  367.       awarifield[5-cfield][(cplayer+1)%2]=0;
  368.     }
  369.   }
  370.  
  371.   if((cplayer==aplayer)&&(cfield==6)) nextplayer=aplayer; else nextplayer=(aplayer+1)%2;
  372.  
  373.   if(awarifield[6][0]>18) return AM_1WINS;
  374.   if(awarifield[6][1]>18) return AM_2WINS;
  375.   if( (awarifield[0][nextplayer]==0) &&
  376.       (awarifield[1][nextplayer]==0) &&
  377.       (awarifield[2][nextplayer]==0) &&
  378.       (awarifield[3][nextplayer]==0) &&
  379.       (awarifield[4][nextplayer]==0) &&
  380.       (awarifield[5][nextplayer]==0) )
  381.   {
  382.     if(awarifield[6][0]==awarifield[6][1]) return AM_TIE;
  383.     if(awarifield[6][0]>awarifield[6][1]) return AM_1WINS;
  384.     return AM_2WINS;
  385.   }
  386.  
  387.   if(nextplayer==aplayer) return AM_EXTRATURN; else return AM_OK;
  388. }
  389.  
  390.  
  391. /////////////////////////////////////////////////////////////////////////////////////////////////////////////
  392. //////////////////////////////////////////////////////////////////////////////////////// Helping functions //
  393. /////////////////////////////////////////////////////////////////////////////////////////////////////////////
  394.  
  395. VOID SetInfoString(STRPTR istr)
  396. {
  397.   TR_SetAttribute(main_project,101,TRAT_Text,(ULONG)istr);
  398. }
  399.  
  400.  
  401. VOID StartGame()
  402. {
  403.   for(i=0;i<=1;i++)
  404.   {
  405.     for(j=0;j<=5;j++) playfield[j][i]=3;
  406.     playfield[6][i]=0;
  407.   }
  408.  
  409.   TR_SetAttribute(main_project,102,TRAT_Disabled,1L);
  410.   TR_SetAttribute(main_project,103,TRAT_Disabled,1L);
  411.   TR_SetAttribute(main_project,104,TRAT_Disabled,1L);
  412.   TR_SetAttribute(main_project,105,TRAT_Disabled,1L);
  413.   TR_SetAttribute(main_project,110,TRAT_Disabled,1L);
  414.   player1=TR_GetAttribute(main_project,102,TRAT_Value);
  415.   player2=TR_GetAttribute(main_project,103,TRAT_Value);
  416.   first=TR_GetAttribute(main_project,104,TRAT_Value);
  417.   level=TR_GetAttribute(main_project,105,TRAT_Value)+1;
  418.   if((player1==0)||(player2==0))
  419.   {
  420.     TR_SetAttribute(main_project,112,TRAT_Disabled,0L);
  421.     TR_SetAttribute(main_project,111,TRAT_Disabled,0L);
  422.   }
  423.   if(first==2) currentplayer=((MyRand())&(1<<7))>>7; else currentplayer=first;
  424.   gamerunning=TRUE;
  425.  
  426.   ActualizeDisplay();
  427.  
  428.   MakeTurn(currentplayer,TRUE);
  429. }
  430.  
  431.  
  432. VOID QuitGame()
  433. {
  434.   TR_SetAttribute(main_project,102,TRAT_Disabled,0L);
  435.   TR_SetAttribute(main_project,103,TRAT_Disabled,0L);
  436.   TR_SetAttribute(main_project,104,TRAT_Disabled,0L);
  437.   TR_SetAttribute(main_project,105,TRAT_Disabled,0L);
  438.   TR_SetAttribute(main_project,112,TRAT_Disabled,1L);
  439.   TR_SetAttribute(main_project,111,TRAT_Disabled,1L);
  440.   TR_SetAttribute(main_project,110,TRAT_Disabled,0L);
  441.   DisablePositionGadgets();
  442.   gamerunning=FALSE;
  443. }
  444.  
  445.  
  446. VOID Winner(UWORD player)
  447. {
  448.   QuitGame();
  449.   switch(player)
  450.   {
  451.     case 0:
  452.       SetInfoString("Player 1 wins.");
  453.       break;
  454.  
  455.     case 1:
  456.       SetInfoString("Player 2 wins.");
  457.       break;
  458.  
  459.     default:
  460.       SetInfoString("A tie.");
  461.       break;
  462.   }
  463. }
  464.  
  465.  
  466. VOID MakeTurn(UWORD player, BOOL setsecondturn)
  467. {
  468.   if(setsecondturn) secondturn=FALSE;
  469.  
  470.   if(player==0)
  471.   {
  472.     if(player1==0)
  473.     {
  474.       SetInfoString("Make your turn, player 1.");
  475.       SetPositionGadgets(0);
  476.     }
  477.     else
  478.     {
  479.       SetInfoString("Player 1 is thinking...");
  480.       DisablePositionGadgets();
  481.       ComputeMove(0);
  482.     }
  483.   }
  484.   else
  485.   {
  486.     if(player2==0)
  487.     {
  488.       SetInfoString("Make your turn, player 2.");
  489.       SetPositionGadgets(1);
  490.     }
  491.     else
  492.     {
  493.       SetInfoString("Player 2 is thinking...");
  494.       DisablePositionGadgets();
  495.       ComputeMove(1);
  496.     }
  497.   }
  498. }
  499.  
  500.  
  501. VOID SetPositionGadgets(UWORD player)
  502. {
  503.   BOOL newval;
  504.   UWORD k;
  505.  
  506.   for(j=0;j<=5;j++)
  507.   {
  508.     newval=playfield[j][player]?0L:1L;
  509.     if(player==0) k=5-j; else k=j;
  510.     if(posgaddisabled[k]!=newval?1L:0L)
  511.     {
  512.       TR_SetAttribute(main_project,201+k,TRAT_Disabled,(UWORD)newval);
  513.       posgaddisabled[k]=newval;
  514.     }
  515.   }
  516. }
  517.  
  518.  
  519. VOID DisablePositionGadgets(VOID)
  520. {
  521.   for(j=0;j<=5;j++) if(!posgaddisabled[j])
  522.   {
  523.     TR_SetAttribute(main_project,201+j,TRAT_Disabled,1L);
  524.     posgaddisabled[j]=1L;
  525.   }
  526. }
  527.  
  528.  
  529. VOID ActualizeDisplay()
  530. {
  531.   for(i=0;i<=1;i++) for(j=0;j<=6;j++) if(display[j][i]!=playfield[j][i])
  532.   {
  533.     display[j][i]=playfield[j][i];
  534.     TR_SetAttribute(main_project,1+(i*10)+j,TRAT_Value,playfield[j][i]);
  535.   }
  536. }
  537.  
  538.  
  539. VOID PerformMove(UWORD player, UWORD field)
  540. {
  541.   UWORD result;
  542.  
  543.   result=AwariMove(playfield,player,field);
  544.   ActualizeDisplay();
  545.  
  546.   switch(result)
  547.   {
  548.     case AM_1WINS:
  549.     case AM_2WINS:
  550.     case AM_TIE:
  551.       Winner(result-3);
  552.       return;
  553.  
  554.     case AM_EXTRATURN:
  555.       if(!secondturn)
  556.       {
  557.         secondturn=TRUE;
  558.         SetPositionGadgets(currentplayer);
  559.         if(currentplayer==0)
  560.         {
  561.           if(player1==0) SetInfoString("Extra turn, player 1.");
  562.           else
  563.           {
  564.             SetInfoString("Extra turn. Player 1 is thinking...");
  565.             DisablePositionGadgets();
  566.             ComputeMove(0);
  567.           }
  568.         }
  569.         else
  570.         {
  571.           if(player2==0) SetInfoString("Extra turn, player 2.");
  572.           else
  573.           {
  574.             SetInfoString("Extra turn. Player 2 is thinking...");
  575.             DisablePositionGadgets();
  576.             ComputeMove(1);
  577.           }
  578.         }
  579.         return;
  580.       }
  581.  
  582.     case AM_OK:
  583.       currentplayer++;
  584.       currentplayer%=2;
  585.       MakeTurn(currentplayer,TRUE);
  586.       return;
  587.  
  588.     case AM_EMPTYFIELD:
  589.       DisplayBeep(NULL);
  590.       return;
  591.   }
  592. }
  593.  
  594.  
  595. VOID ComputeMove(UWORD player)
  596. {
  597.   UWORD num;
  598.  
  599.   TR_LockProject(main_project);
  600.   //Delay(50L);
  601.  
  602.   currentdepth=0;
  603.   num=BestMove(playfield,player,NULL);
  604.  
  605.   if(playfield[num][player]) PerformMove(player,num);
  606.   else if(playfield[0][player]) PerformMove(player,0);
  607.   else if(playfield[1][player]) PerformMove(player,1);
  608.   else if(playfield[2][player]) PerformMove(player,2);
  609.   else if(playfield[3][player]) PerformMove(player,3);
  610.   else if(playfield[4][player]) PerformMove(player,4);
  611.   else if(playfield[5][player]) PerformMove(player,5);
  612.   else PerformMove(currentplayer,2);
  613.  
  614.   TR_UnlockProject(main_project);
  615. }
  616.  
  617.  
  618. UWORD BestMove(UBYTE awarifield[7][2], UWORD aplayer, UWORD *bestval)
  619. {
  620.   UBYTE dest[6][7][2];
  621.   register UWORD result;
  622.   register UWORD i,j,k;
  623.   register UBYTE val=0, newval, retval=0;
  624.   UWORD recurseval,otherplayer;
  625.  
  626.   currentdepth++;
  627.  
  628.   for(i=0;i<7;i++) for(j=0;j<2;j++) for(k=0;k<6;k++) dest[k][i][j]=awarifield[i][j];
  629.  
  630.   for(k=0;k<6;k++)
  631.   {
  632.     if(currentdepth>=level)
  633.     {
  634.       result=AwariMove(dest[k],aplayer,k);
  635.       newval=dest[k][6][aplayer];
  636.       switch(result)
  637.       {
  638.         case AM_EXTRATURN:
  639.           newval++;
  640.           break;
  641.         case AM_1WINS:
  642.           if(aplayer==0) newval=255; else newval=0;
  643.           break;
  644.         case AM_2WINS:
  645.           if(aplayer==1) newval=255; else newval=0;
  646.           break;
  647.         case AM_TIE:
  648.           if(newval>0) newval--;
  649.           break;
  650.         case AM_EMPTYFIELD:
  651.           newval=0;
  652.           break;
  653.       }
  654.     }
  655.     else
  656.     {
  657.       if((result=AwariMove(dest[k],aplayer,k)==AM_EXTRATURN)&&((secondturn==FALSE)||(currentdepth>1)))
  658.         result=AwariMove(dest[k],aplayer,BestMoveNR(dest[k],aplayer));
  659.       otherplayer=(aplayer+1)%2;
  660.       if(AwariMove(dest[k],otherplayer,BestMoveNR(dest[k],otherplayer))==AM_EXTRATURN)
  661.         AwariMove(dest[k],otherplayer,BestMoveNR(dest[k],otherplayer));
  662.       BestMove(dest[k],aplayer,&recurseval);
  663.       newval=recurseval;
  664.       if((result==AM_EXTRATURN)&&((secondturn==FALSE)||(currentdepth>1))) newval++;
  665.     }
  666.     if( (newval>val) || ((newval==val)&&( ((MyRand())&(1<<7))>>7 == 1)) )
  667.     {
  668.       val=newval;
  669.       retval=k;
  670.     }
  671.   }
  672.  
  673.   currentdepth--;
  674.   if(bestval) *bestval=val;
  675.   return retval;
  676. }
  677.  
  678.  
  679. UWORD BestMoveNR(UBYTE awarifield[7][2], UWORD aplayer)
  680. {
  681.   UBYTE dest[6][7][2];
  682.   register UWORD result;
  683.   register UWORD i,j,k;
  684.   register UBYTE val=0, newval, retval=0;
  685.  
  686.   for(i=0;i<7;i++) for(j=0;j<2;j++) for(k=0;k<6;k++) dest[k][i][j]=awarifield[i][j];
  687.  
  688.   for(k=0;k<6;k++)
  689.   {
  690.     result=AwariMove(dest[k],aplayer,k);
  691.     newval=dest[k][6][aplayer];
  692.     switch(result)
  693.     {
  694.       case AM_EXTRATURN:
  695.         newval++;
  696.         break;
  697.       case AM_1WINS:
  698.         if(aplayer==0) newval=255; else newval=0;
  699.         break;
  700.       case AM_2WINS:
  701.         if(aplayer==1) newval=255; else newval=0;
  702.         break;
  703.       case AM_TIE:
  704.         if(newval>0) newval--;
  705.         break;
  706.       case AM_EMPTYFIELD:
  707.         newval=0;
  708.         break;
  709.     }
  710.     if( (newval>val) || ((newval==val)&&( ((MyRand())&(1<<7))>>7 == 1)) )
  711.     {
  712.       val=newval;
  713.       retval=k;
  714.     }
  715.   }
  716.  
  717.   return retval;
  718. }
  719.